#include "ppm.h"
#include "main.h"

/*
    PPM USE PB6 (UART1 TX PIN)
    PPM USE TIMER3 for count time
*/

uint16_t ppm_data[PPM_CHANNEL_NUM];
uint8_t ppm_index=0;
uint8_t ppm_start_flag=0;
uint8_t ppm_lost_flag = 1;

 

void ppm_init(void)
{
    LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
    LL_TIM_InitTypeDef TIM_InitStruct = {0};
    
    /* GPIO Ports Clock Enable */
    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
    
    LL_EXTI_SetEXTISource(LL_EXTI_CONFIG_PORTB, LL_EXTI_CONFIG_LINE6);
    
    EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
    EXTI_InitStruct.LineCommand = ENABLE;
    EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
    EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_RISING_FALLING;
    LL_EXTI_Init(&EXTI_InitStruct);
    
    LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_6, LL_GPIO_PULL_NO);    
    LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT);
    
    /* EXTI interrupt init*/
    NVIC_SetPriority(EXTI4_15_IRQn, 0);
    NVIC_EnableIRQ(EXTI4_15_IRQn);


    /* Peripheral clock enable */
    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);

    NVIC_SetPriority(TIM3_IRQn, 0);
    NVIC_EnableIRQ(TIM3_IRQn);

    TIM_InitStruct.Prescaler = 64-1;
    TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
    TIM_InitStruct.Autoreload = 65535;
    TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
    LL_TIM_Init(TIM3, &TIM_InitStruct);
    LL_TIM_DisableARRPreload(TIM3);
    LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
    LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
    LL_TIM_DisableMasterSlaveMode(TIM3);

    LL_TIM_EnableCounter(TIM3);
}

void ppm_gpio_irq_callback(uint8_t pin_state)
{
    uint16_t timer_val;
    
    if(pin_state)   //gpio jump high
    {
        timer_val = LL_TIM_GetCounter(TIM3);

        LL_TIM_SetCounter(TIM3,0);

        if(timer_val > 2500)
        {
            if(ppm_index) //index > 0,have received one frame
            {                
                ppm_lost_flag = 0;
            }
            
            ppm_start_flag = 1;
            ppm_index = 0;
        }
        else
        {
            if(ppm_start_flag)
            {
                ppm_data[ppm_index] = timer_val;
                ppm_index++;
                if(ppm_index >= PPM_CHANNEL_NUM)
                {
                    ppm_start_flag = 0;
                }
            }
        }
    }
	else
	{

	}

}

void ppm_timer_irq_callback(void)
{
    ppm_lost_flag = 1;
    ppm_index = 0;
    ppm_start_flag = 0;
}

/**
  * @brief This function handles EXTI line 4 to 15 interrupts.
  */
void EXTI4_15_IRQHandler(void)
{
    if (LL_EXTI_IsActiveRisingFlag_0_31(LL_EXTI_LINE_6) != RESET)
    {
        LL_EXTI_ClearRisingFlag_0_31(LL_EXTI_LINE_6);
        
        ppm_gpio_irq_callback(1);
    }
    
    if (LL_EXTI_IsActiveFallingFlag_0_31(LL_EXTI_LINE_6) != RESET)
    {
        LL_EXTI_ClearFallingFlag_0_31(LL_EXTI_LINE_6);
        
        ppm_gpio_irq_callback(0);
    }
}


/**
  * @brief This function handles TIM3 global interrupt.
  */
void TIM3_IRQHandler(void)
{
    if(LL_TIM_IsActiveFlag_UPDATE(TIM3))
    {
        LL_TIM_ClearFlag_UPDATE(TIM3);

        ppm_timer_irq_callback();
    }
}


/* public */
uint8_t ppm_is_lost(void)
{
    return ppm_lost_flag;
}

uint8_t ppm_get_data(uint8_t * buf)
{
    memcpy(buf,ppm_data,PPM_CHANNEL_NUM);
    
    return 0;
}

